#pragma once

#include "ProjectItem.hpp"




namespace Engine
{
	namespace Edit
	{
		class Project
			: public ProjectItem
		{
			friend ProjectItem;

		public:

			SHARED(Project);

		protected:

			/**
			 * Creates a new empty project with the given title and the given filename.
			 */
			Project(QString title, QFileInfo file);

			/**
			 * Loads a new project from the given dom stream.
			 */
			//Project(AbstractDomInputStream* stream, QFileInfo file);

			virtual void post_create(ptr _this);

		protected:

			notify    m_modified; //< Is emitted on name changed, add child and remove child of this OR a child

		public:

			MAKE_SHARED2(Project, QString, QFileInfo);



			/**
			 * @returns the type of item
			 */
			virtual Type type() const;


			ProjectItem::ptr scripts() const;
			ProjectItem::ptr uiDefinitions() const;
			ProjectItem::ptr materials() const;
			ProjectItem::ptr meshes() const;



			/**
			 * Loads the project from the given stream.
			 */
			virtual void load(AbstractDomInputStream& stream);

			/**
			 * Saves the project to the given stream.
			 */
			virtual void save(AbstractDomOutputStream& stream) const;

			boostext::connector<notify>   modified;

		protected:

			/**
			 * This function is called by children (or this one) to indicate certain events that modify
			 * the tree.
			 */
			Result emitModified(ProjectItem::weak_ptr sender, ProjectItem::weak_ptr item, Action action);

			/**
			 * Facilitates an item of the expected type and tries to load it from the
			 * stream.
			 *
			 * @throws if there's an error during loading
			 */
			template <typename Expected>
			void load(ProjectItem::ptr parent, QString name, AbstractDomInputStream& stream)
			{
				stream.openElement(name);
				verify(stream.hasAttribute("count"));
				std::size_t count = stream.attribute("count").toUInt();

				for(std::size_t i = 0; i < count; ++i)
				{
					auto item = Expected::create(weak_from_this(), "unnamed");
					item->load(stream);
					parent->add(item);
				}

				stream.closeElement(name);
			}

			void save(ProjectItem::const_ptr item, QString name, AbstractDomOutputStream& stream) const;

		private:

			QFileInfo          m_file;
		};
		///////////////////////////////////////////////////////////////////////////////////////////

		Q_DECLARE_METATYPE(Project::ptr);
	}
	///////////////////////////////////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////////////////////////
